package wsi.gui.detector;

import java.util.List;

import org.rygh.gui.model.callback.Callback;
import org.rygh.gui.swing.common.text.STextPresenter;
import org.rygh.gui.swing.common.view.SProgressGlass;
import org.rygh.gui.swing.component.STextArea;
import org.rygh.gui.swing.field.SIntegerField;
import org.rygh.gui.swing.field.SStringField;
import org.rygh.gui.swing.presenter.SwingPresenter;
import org.rygh.gui.swing.table.STableView;
import org.rygh.semantic.gui.swing.YagoAssistPresenter;
import org.rygh.semantic.gui.swing.input.Input;
import org.rygh.semantic.model.ex.SampleWorker;
import org.rygh.semantic.sparql.QueryComposer;
import org.rygh.semantic.sparql.SparQL;

import wsi.function.Function;
import wsi.gui.function.select.FunctionSelectPresenter;

@SuppressWarnings("deprecation")
public class DetectorPresenter extends SwingPresenter {

	public interface Display extends SwingPresenter.Display {

		SStringField getFunctionField();

		SIntegerField getLimitField();

		STextArea getQueryArea();

		STableView getTable();

	}

	private final DetectorTableModel tableModel = new DetectorTableModel();
	private final YagoAssistPresenter assistPresenter;
	private FunctionSelectPresenter functionSelectPresenter;
	private Function function;
	private SparQL query;
	private STextPresenter inputPresenter;

	public DetectorPresenter() {
		display = new DetectorWindow(this);
		assistPresenter = new YagoAssistPresenter(getWindow());

		bind();
	}

	@Override
	protected void bind() {
		super.bind();

		final Display d = (Display) display;

		d.getTable().setModel(tableModel);

		assistPresenter.bind(d.getQueryArea());
	}

	public void detect() {
		if (function == null) {
			getWindow().message("Select function first.");
			return;
		}

		final Display d = (Display) display;
		QueryComposer comp = new QueryComposer(d.getQueryArea().getText());
		query = comp.compose();
		query.distinct("?x");

		SProgressGlass<List<Input>> progress = getWindow().progress(
				"Gather top entities with large degrees...",
				new Callback<List<Input>>() {

					@Override
					public void call(final List<Input> value) {
						detectCalling(value);
					}
				});
		SampleWorker worker = new SampleWorker(progress, query, null);
		progress.setWorker(worker);
		progress.run();

	}

	private void detectCalling(List<Input> list) {
		if (list.isEmpty()) {
			getWindow().message("No entities selected.");
			return;
		}

		Display d = (Display) display;
		int limit = Integer.parseInt(d.getLimitField().getValue().toString());

		SProgressGlass<List<DetectorTuple>> progress = getWindow().progress(
				"Detecting input values for function...",
				new Callback<List<DetectorTuple>>() {

					@Override
					public void call(List<DetectorTuple> tuples) {
						tableModel.clear();

						for (DetectorTuple i : tuples)
							tableModel.add(i);

						tableModel.fireTableDataChanged();
					}
				});

		DetectWorker worker = new DetectWorker(progress, list, function, limit);
		progress.setWorker(worker);
		progress.run();

	}

	public void selectFunction() {
		final Display d = (Display) display;

		if (functionSelectPresenter == null)
			functionSelectPresenter = new FunctionSelectPresenter();

		functionSelectPresenter.display();
		functionSelectPresenter.setCallback(new Callback<Function>() {

			@Override
			public void call(Function value) {
				function = value;
				d.getFunctionField().setText(function.getName());
			}
		});
	}

	public void viewInputs() {
		if (inputPresenter == null)
			inputPresenter = new STextPresenter();

		StringBuilder sbuilder = new StringBuilder();

		final Display d = (Display) display;

		for (int i = 0; i < tableModel.getRowCount(); i++) {
			int index = d.getTable().convertRowIndexToModel(i);

			sbuilder.append(String.format("%s\n", tableModel.get(index)
					.getName()));
		}

		inputPresenter.load(sbuilder.toString());
		inputPresenter.display();
	}
}
